/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package service;

import com.openbrew.openbrewrf.Administration;
import com.openbrew.openbrewrf.BoilHops;
import com.openbrew.openbrewrf.DryHops;
import com.openbrew.openbrewrf.MaltBill;
import com.openbrew.openbrewrf.RecipeAdditives;
import com.openbrew.openbrewrf.Recipes;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import javax.ejb.Stateless;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.StreamingOutput;
import pdf.RecipePDFCreator;
import tools.RecipeTools;

/**
 *
 * @author chapmand
 */
@Stateless
@Path("com.openbrew.openbrewrf.recipes")
public class RecipesFacadeREST extends AbstractFacade<Recipes> {
    @PersistenceContext(unitName = "com.openBrew_openBrewRF_war_1.0PU")
    private EntityManager em;

    public RecipesFacadeREST() {
        super(Recipes.class);
    }

    @POST
    @Override
    @WebMethod(operationName = "create")
    @Consumes({"application/xml", "application/json"})
    public Recipes create(@WebParam(name = "recipes") Recipes entity) {
        //Create Malt Bill
        if(entity.getMaltBillCollection()!=null){
            List<MaltBill> lines = new ArrayList<MaltBill>();
            for(final MaltBill mb : entity.getMaltBillCollection()){
                if(mb.getMaltBillID()== null || mb.getMaltBillID() == 0){
                    lines.add(createMaltBill(mb));
                } else {
                    lines.add(mb);
                }
            }
            entity.setMaltBillCollection(lines);
        }
        //Create Boil Hops
        if(entity.getBoilHopCollection()!=null){
            List<BoilHops> lines = new ArrayList<BoilHops>();
            for(final BoilHops bh : entity.getBoilHopCollection()){
                if(bh.getBoilHopsID()== null || bh.getBoilHopsID() == 0){
                    lines.add(createBoilHop(bh));
                } else {
                    lines.add(bh);
                }
            }
            entity.setBoilHopCollection(lines);
        }
        //Create Dry Hops
        if(entity.getDryHopCollection()!=null){
            List<DryHops> lines = new ArrayList<DryHops>();
            for(final DryHops dh : entity.getDryHopCollection()){
                if(dh.getDryHopID()== null || dh.getDryHopID() == 0){
                    lines.add(createDryHop(dh));
                } else {
                    lines.add(dh);
                }
            }
            entity.setDryHopCollection(lines);
        }
        //Create Additives
        if(entity.getAdditiveCollection()!=null){
            List<RecipeAdditives> lines = new ArrayList<RecipeAdditives>();
            for(final RecipeAdditives add : entity.getAdditiveCollection()){
                if(add.getAdditiveID()== null || add.getAdditiveID() == 0){
                    lines.add(createRecipeAdditive(add));
                } else {
                    lines.add(add);
                }
            }
            entity.setAdditiveCollection(lines);
        }
        entity = super.create(entity);
        return entity;
    }

    @PUT
    @Override
    @Consumes({"application/xml", "application/json"})
    public void edit(Recipes entity) {
        RecipeTools rt = new RecipeTools();
        //Update Malt Bill
        if(entity.getMaltBillCollection()!=null){
            List<MaltBill> lines = new ArrayList<MaltBill>();
            for(final MaltBill mb : entity.getMaltBillCollection()){
                if(mb.getMaltBillID()== null || mb.getMaltBillID() == 0){
                    lines.add(createMaltBill(mb));
                } else {
                    getEntityManager().merge(mb);
                    lines.add(mb);
                }
            }
            
            entity.setMaltBillCollection(lines);
        }
        //Update Boil Hops
        if(entity.getBoilHopCollection()!=null){
            List<BoilHops> lines = new ArrayList<BoilHops>();
            for(final BoilHops bh : entity.getBoilHopCollection()){
                if(bh.getBoilHopsID()== null || bh.getBoilHopsID() == 0){
                    lines.add(createBoilHop(bh));
                } else {
                    getEntityManager().merge(bh);
                    lines.add(bh);
                }
            }
            
            entity.setBoilHopCollection(lines);
        }
        //Update Dry Hops
        if(entity.getDryHopCollection()!=null){
            List<DryHops> lines = new ArrayList<DryHops>();
            for(final DryHops dh : entity.getDryHopCollection()){
                if(dh.getDryHopID()== null || dh.getDryHopID() == 0){
                    lines.add(createDryHop(dh));
                } else {
                    getEntityManager().merge(dh);
                    lines.add(dh);
                }
            }
            
            entity.setDryHopCollection(lines);
        }
        //Update Recipe Additives
        if(entity.getAdditiveCollection()!=null){
            List<RecipeAdditives> lines = new ArrayList<RecipeAdditives>();
            for(final RecipeAdditives add : entity.getAdditiveCollection()){
                if(add.getAdditiveID()== null || add.getAdditiveID() == 0){
                    lines.add(createRecipeAdditive(add));
                } else {
                    getEntityManager().merge(add);
                    lines.add(add);
                }
            }
            
            entity.setAdditiveCollection(lines);
        }
        
        //Now look if the name has changed, if so we need to update old revisions to same name;
        rt.checkNameChange(em, entity);
        
        super.edit(entity);
    }
    
    private MaltBill createMaltBill(final MaltBill mb){
        getEntityManager().persist(mb);
        getEntityManager().flush();
        getEntityManager().refresh(mb);
        return mb;
    }
    
    private BoilHops createBoilHop(final BoilHops bh){
        getEntityManager().persist(bh);
        getEntityManager().flush();
        getEntityManager().refresh(bh);
        return bh;
    }
    
    private DryHops createDryHop(final DryHops dh){
        getEntityManager().persist(dh);
        getEntityManager().flush();
        getEntityManager().refresh(dh);
        return dh;
    }
    
    private RecipeAdditives createRecipeAdditive(final RecipeAdditives ra){
        getEntityManager().persist(ra);
        getEntityManager().flush();
        getEntityManager().refresh(ra);
        return ra;
    }

    @DELETE
    @Path("{id}")
    public void remove(@PathParam("id") Integer id) {
        super.remove(super.find(id));
    }

    @GET
    @Path("{id}")
    @Produces({"application/xml", "application/json"})
    public Recipes find(@PathParam("id") Integer id) {
        return super.find(id);
    }

    @GET
    @Path("{id}/recipe_pdf")
    @Produces({"application/pdf"})
    public StreamingOutput findHeaderImg(@PathParam("id") Integer id) {
        final Recipes recipe = super.find(id);
        return new StreamingOutput() {
            @Override
            public void write(OutputStream output) throws IOException, WebApplicationException {
                try {
                    final Administration admin = getAdmin(em);
                    final RecipePDFCreator recppdf = new RecipePDFCreator();
                    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
                    recppdf.createPDF(outputStream, recipe, admin);
                    byte[] bytes = outputStream.toByteArray();
                    output.write(bytes);
                } catch (IOException e) {
                    throw new WebApplicationException(e);
                }
            }
        };
    }
    
    /***************************************************************************
     * Database modification functions.
     **************************************************************************/
    private Administration getAdmin(final EntityManager en){
        TypedQuery<Administration> query = en.createQuery(
            "SELECT a FROM Administration a WHERE a.aNum = '1'", Administration.class);
        Administration admin = query.getSingleResult();
        return admin;
    }

    @GET
    @Override
    @Produces({"application/xml", "application/json"})
    public List<Recipes> findAll() {
        return super.findAll();
    }

    @GET
    @Path("{from}/{to}")
    @Produces({"application/xml", "application/json"})
    public List<Recipes> findRange(@PathParam("from") Integer from, @PathParam("to") Integer to) {
        return super.findRange(new int[]{from, to});
    }
    
    @GET
    @Path("runNamedQuery/{str}")
    @Override
    @Produces({"application/xml", "application/json"})
    public List<Recipes> runNamedQuery(@PathParam("str") String str){
        return super.runNamedQuery(str);
    }

    @GET
    @Path("count")
    @Produces("text/plain")
    public String countREST() {
        return String.valueOf(super.count());
    }

    @Override
    protected EntityManager getEntityManager() {
        return em;
    }
    
}
